
unsigned long __attribute__((section(".data")))arg;


float FPP_TO_IEEE(unsigned long fppzahl);
unsigned long IEEE_TO_FPP(float zahl);

unsigned long sinus(void);
unsigned long cosinus(void);
unsigned long sinush(void);
unsigned long cosinush(void);
unsigned long tangens(void);
unsigned long tangensh(void);
unsigned long cotangens(void);
unsigned long cotangensh(void);

unsigned long logarithmus(void);
unsigned long exponent(void);
unsigned long sqareroot(void);
unsigned long cubicroot(void);




unsigned long IEEE_TO_FPP(float zahl)
{
    unsigned long  retval;
	unsigned short exponent = 0;
	unsigned short highword = 0;
	unsigned short *pusHigh;

    retval = *((unsigned long *)&zahl);
	pusHigh = (unsigned short *)&retval;

	pusHigh++;						// Pointer um 2 erhoehen

	highword = *pusHigh;

	retval &= 0x007FFFFF;				// Exponent und Vorzeichen ausblenden
	exponent = (highword >> 7);
	exponent = exponent+1;				// Exponent um 1 erhoehen, da BIAS des FPP-Formats 128 ist
	if(highword & 0x8000)
	{
		retval |= 0x00800000;			// Vorzeichen an neuer Stelle einblenden
	}
	exponent <<= 8;
	*pusHigh |= exponent;

	return(retval);

}

float FPP_TO_IEEE(unsigned long fppzahl)
{
    unsigned short *pus;
    unsigned short exponent;
    unsigned short highword;
    float retval;

    pus = (unsigned short *)&fppzahl;
    pus++;
    exponent = *pus;
    exponent >>= 8;
    exponent--;
    *(unsigned long *)&retval = *(unsigned long *)&fppzahl;   //kopieren
    pus = (unsigned short *)&retval;
    pus++;
    highword = *pus;					// retten
    *pus &= 0x007F;
    if(highword & 0x0080)
    {
        *pus |= 0x8000;
    }
    exponent <<= 7;
    *pus |= exponent;
    return(retval);
}




unsigned long sinus(void)
{
	asm("call 	#FLT_SAV");
	//asm("sub	#4,R1");				// R1 ist der Stackpointer
	asm("mov %0,R5"::"m"(&arg));
	asm("add    #2,R5");				// R5 muss auf die MSB zeigen
	asm("call #FLT_SIN");

	//  Stackpointer und R5 zeigen beide auf den H-Teil des Ergebnisses

	asm("mov	0(R5),R15");
//	asm("mov	0(R5),%0"::"r"(ergebnis));
	asm("mov	2(R5),R14");
//	asm("mov	2(R5),%0"::"r"(ergebnis));
	asm("call	#FLT_REC");
}


unsigned long cosinus(void)
{
	asm("call 	#FLT_SAV");
	//asm("sub	#4,R1");				// R1 ist der Stackpointer
	asm("mov %0,R5"::"m"(&arg));
	asm("add    #2,R5");				// R5 muss auf die MSB zeigen
	asm("call #FLT_COS");

	//  Stackpointer und R5 zeigen beide auf den H-Teil des Ergebnisses

	asm("mov	0(R5),R15");
	asm("mov	2(R5),R14");
	asm("call	#FLT_REC");
}

unsigned long tangens(void)
{
	asm("call 	#FLT_SAV");
	//asm("sub	#4,R1");				// R1 ist der Stackpointer
	asm("mov %0,R5"::"m"(&arg));
	asm("add    #2,R5");				// R5 muss auf die MSB zeigen
	asm("call #FLT_TAN");

	//  Stackpointer und R5 zeigen beide auf den H-Teil des Ergebnisses

	asm("mov	0(R5),R15");
	asm("mov	2(R5),R14");
	asm("call	#FLT_REC");
}

unsigned long tangensh(void)
{
	asm("call 	#FLT_SAV");
	//asm("sub	#4,R1");				// R1 ist der Stackpointer
	asm("mov %0,R5"::"m"(&arg));
	asm("add    #2,R5");				// R5 muss auf die MSB zeigen
	asm("call #FLT_TANH");

	//  Stackpointer und R5 zeigen beide auf den H-Teil des Ergebnisses

	asm("mov	0(R5),R15");
	asm("mov	2(R5),R14");
	asm("call	#FLT_REC");
}

unsigned long cotangens(void)
{
	asm("call 	#FLT_SAV");
	//asm("sub	#4,R1");				// R1 ist der Stackpointer
	asm("mov %0,R5"::"m"(&arg));
	asm("add    #2,R5");				// R5 muss auf die MSB zeigen
	asm("call #FLT_COT");

	//  Stackpointer und R5 zeigen beide auf den H-Teil des Ergebnisses

	asm("mov	0(R5),R15");
	asm("mov	2(R5),R14");
	asm("call	#FLT_REC");
}

unsigned long cotangensh(void)
{
	asm("call 	#FLT_SAV");
	//asm("sub	#4,R1");				// R1 ist der Stackpointer
	asm("mov %0,R5"::"m"(&arg));
	asm("add    #2,R5");				// R5 muss auf die MSB zeigen
	asm("call #FLT_COTH");

	//  Stackpointer und R5 zeigen beide auf den H-Teil des Ergebnisses

	asm("mov	0(R5),R15");
	asm("mov	2(R5),R14");
	asm("call	#FLT_REC");
}

unsigned long sinush(void)
{
	asm("call 	#FLT_SAV");
	asm("mov %0,R5"::"m"(&arg));
	asm("add    #2,R5");				// R5 muss auf die MSB zeigen
	asm("call #FLT_SINH");

	//  Stackpointer und R5 zeigen beide auf den H-Teil des Ergebnisses

	asm("mov	0(R5),R15");
	asm("mov	2(R5),R14");
	asm("call	#FLT_REC");
}


unsigned long cosinush(void)
{
	asm("call 	#FLT_SAV");
	//asm("sub	#4,R1");				// R1 ist der Stackpointer
	asm("mov %0,R5"::"m"(&arg));
	asm("add    #2,R5");				// R5 muss auf die MSB zeigen
	asm("call #FLT_COSH");

	//  Stackpointer und R5 zeigen beide auf den H-Teil des Ergebnisses

	asm("mov	0(R5),R15");
//	asm("mov	0(R5),%0"::"r"(ergebnis));
	asm("mov	2(R5),R14");
//	asm("mov	2(R5),%0"::"r"(ergebnis));
	asm("call	#FLT_REC");
}

unsigned long logarithmus(void)
{
	asm("call 	#FLT_SAV");
	asm("mov %0,R5"::"m"(&arg));
	asm("add    #2,R5");				// R5 muss auf die MSB zeigen
	asm("call #FLT_LN");

	//  Stackpointer und R5 zeigen beide auf den H-Teil des Ergebnisses

	asm("mov	0(R5),R15");
	asm("mov	2(R5),R14");
	asm("call	#FLT_REC");
}

unsigned long exponent(void)
{
	asm("call 	#FLT_SAV");
	asm("mov %0,R5"::"m"(&arg));
	asm("add    #2,R5");				// R5 muss auf die MSB zeigen
	asm("call #FLT_EXP");

	//  Stackpointer und R5 zeigen beide auf den H-Teil des Ergebnisses

	asm("mov	0(R5),R15");
	asm("mov	2(R5),R14");
	asm("call	#FLT_REC");
}

unsigned long sqareroot(void)
{
	asm("call 	#FLT_SAV");
	asm("mov %0,R5"::"m"(&arg));
	asm("add    #2,R5");				// R5 muss auf die MSB zeigen
	asm("call #FLT_SQRT");

	//  Stackpointer und R5 zeigen beide auf den H-Teil des Ergebnisses

	asm("mov	0(R5),R15");
	asm("mov	2(R5),R14");
	asm("call	#FLT_REC");
}

unsigned long cubicroot(void)
{
	asm("call 	#FLT_SAV");
	asm("mov %0,R5"::"m"(&arg));
	asm("add    #2,R5");				// R5 muss auf die MSB zeigen
	asm("call #FLT_CBRT");

	//  Stackpointer und R5 zeigen beide auf den H-Teil des Ergebnisses

	asm("mov	0(R5),R15");
	asm("mov	2(R5),R14");
	asm("call	#FLT_REC");
}

float _sin(float argument)
{
	unsigned long ergebnis;

	arg = IEEE_TO_FPP(argument);
	ergebnis = sinus();
	return(FPP_TO_IEEE(ergebnis));

}

float _cos(float argument)
{
	unsigned long ergebnis;

	arg = IEEE_TO_FPP(argument);
	ergebnis = cosinus();
	return(FPP_TO_IEEE(ergebnis));

}

float _tan(float argument)
{
	unsigned long ergebnis;

	arg = IEEE_TO_FPP(argument);
	ergebnis = tangens();
	return(FPP_TO_IEEE(ergebnis));

}

float _tanh(float argument)
{
	unsigned long ergebnis;

	arg = IEEE_TO_FPP(argument);
	ergebnis = tangensh();
	return(FPP_TO_IEEE(ergebnis));

}

float _cot(float argument)
{
	unsigned long ergebnis;

	arg = IEEE_TO_FPP(argument);
	ergebnis = cotangens();
	return(FPP_TO_IEEE(ergebnis));

}

float _coth(float argument)
{
	unsigned long ergebnis;

	arg = IEEE_TO_FPP(argument);
	ergebnis = cotangensh();
	return(FPP_TO_IEEE(ergebnis));

}


float _sinh(float argument)
{
	unsigned long ergebnis;

	arg = IEEE_TO_FPP(argument);
	ergebnis = sinush();
	return(FPP_TO_IEEE(ergebnis));

}

float _cosh(float argument)
{
	unsigned long ergebnis;

	arg = IEEE_TO_FPP(argument);
	ergebnis = cosinush();
	return(FPP_TO_IEEE(ergebnis));

}

float _log(float argument)
{
	unsigned long ergebnis;

	arg = IEEE_TO_FPP(argument);
	ergebnis = logarithmus();
	return(FPP_TO_IEEE(ergebnis));

}

float _exp(float argument)
{
	unsigned long ergebnis;

	arg = IEEE_TO_FPP(argument);
	ergebnis = exponent();
	return(FPP_TO_IEEE(ergebnis));

}

float _sqrt(float argument)
{
	unsigned long ergebnis;

	arg = IEEE_TO_FPP(argument);
	ergebnis = sqareroot();
	return(FPP_TO_IEEE(ergebnis));

}

float _cbrt(float argument)
{
	unsigned long ergebnis;

	arg = IEEE_TO_FPP(argument);
	ergebnis = cubicroot();
	return(FPP_TO_IEEE(ergebnis));

}

